#ifndef CHARACTER_HH_
#   define CHARACTER_HH_

#   include "common/stl.h"

#   include "items/inventory/Inventory.hh"
#   include "input/InputCharacter.hh"
#   include "entities/bodyparts/BodyPart.hh"
#   include "entities/LifeForm.hh"

// TODO: need getters / setters 4 all this mess...

/** a Character is *NOT* limited in nb weapon carrying at the same time
 ** though, he's limited in weight && storage rooms
 ** easier to carry 5 guns: 2 holsters, 1 belt, 1 jacket && 1 in hand
 ** than a rifle in hands and another, oh wait there's no strap
 */

// TODO: fill me
enum e_position
{
    POSITION_CROUCH
};


class Character: public LifeForm
{
    public:
        Character();

        // free resources as Sounds
        ~Character();

        // _________________________ getters / setters _________________________

        // are getters (returning in-cache values) really useful ?

        /// returns in cache globalWeight
        float getWeight();
        /// requesting globalWeight
        float askWeight();

        /// returns in cache globalHeight
        float getHeight();
        /// requesting globalHeight
        float askHeight();

        /// returns in cache globalHealth
        float getHealth();
        /// requesting globalHealth
        float askHealth();

        /// \return true if requested move is allowed
        // bool canMove(Vector direction);

        /** \return false if too close from a wall, crawling, ...
         ** \return (true if crouch && distant from a wall)
         ** insist on request fire in front of wall, play sound
         ** as : "j'ai la geule dans le mur"
         */
        bool canShoot();

        // can we reload ? (under water, crawling, ...)
        /** \return true if character is abble to reload
         ** this method should only be called on request
         ** (we do not need to store an attribute)
         ** returned value is function of
         ** physical condition (dying && crawling => not allowed)
         ** environment && weapon (swimming, not waterproof) [cd be forced]
         ** do *NOT* check if the Gun is already full
         **   this is USER trouble
         **   but cd add a timer: 30 secs not shooting && reload done
         */
        bool canReload();

        /// rm clip, watch it
        bool checkAmmo();

        /** plays / pause breath sound, according to _breath value
         ** evaluate right breath sound to play
         ** playable sounds are:
         **     _soundStand
         **	  _soundWalk
         **	  _soundRun
         ** \return Character is now breathing
         */
        bool breath();

        bool treatShot();

        bool isDead();

        /** \return true if the Character is on ground */
        bool isDown();


        // Updaters
        void updateHealth();
        void updateWeight();
        void updateCharacteristics();

        Vector applyMove(Vector direction);

        // shd be in a CharacterMotion class ?
        void mouseControl();

    private:
        unsigned int _id; // character id // server

        std::vector<BodyPart> _bodyParts;

        // __________ Inventory (on serv) __________
//		Inventory _invBack;
//		Inventory _invFront;
//		Inventory _invSide;
//		Inventory _invHand; // briefcase type

        // __________ attributes (xp dependents, up to the server) __________
        float _strength; /// increase max carriable weight
        float _stamina; /// increase breath
        float _health; /// character health
        float _accuracy; /// coeff to apply on gun accuracy

        // __________ STATUS __________

        // ---------- server part ----------
        Coords _position; /// character position on map

        // ----- global.+ refers to character characteristics, including stuff
        float _globalHealth; /// sum of all body parts health
        float _globalWeight; /// own weight + sum of all stuff weight
        float _globalHeight; /// own height + shoes && helmet height

        float _onGroundHealth; //  'on ground' health (dying but trying to crawl to a safe area)
        float _velocity; /// current velocity
        bool _moving; // shd be only voluntary moves ? // cd add current animation time left
        float _height; /// including shoes && helmet
        float _weight; /// character own weight (without clothes, ...)
        float _money; // block @ MAX_FLOAT // NOTE: watch for better type (we don't need more than 2 digits after coma)
        float _bleeding; /// in millimeters cube per second; calc from weighted sum of all bleeds
        float _breathLevel; // in breath per min / one breath duration / just a level ... ?
        unsigned char _standPosition; // on knee, stand up, crawling

        /** above standard_value: increase velocity
         ** above safety_value, dying (tremble, then fall [~10 min later] ...)
         */
        float _cardioRythm;
        float _vision; // blind coeff // cd affect far rendering / blur effect ? // on serv
        unsigned char _glasses; // standard (correction), sun (+s attenuation levels) // stuff => serv

        /** server side: difference between left && right arm
         ** (wounded in right arm && switch to left-handed)
         ** used to show an item in left or right hand
         */
        bool _rightHanded;

        InputCharacter _input;

        // __________ Media attrs (client part)
        std::string _name; // cd be shared / serv only
        unsigned char _skinColor;
        bool _male;
        unsigned char _voice; /// voice_id column in DB (=f(sex))
        unsigned char _language; /// => voice (=f(sex))

        // ---------- Sounds attrs ----------
        /** list of sounds we'll have to play
         ** this list is sorted by priority
         ** there's only 'voice' Sounds in this list
         ** indeed we can play running sound && "I'm hit"
         **
         ** sort order:
         **   deadly wound - heavy wounds
         **   if clip leftAmmo < 50%
         **     capacity - important wounds
         **   else
         **     important wound - capacity
         **   various status ("I'm cold")
         */
        std::list<Sound> _requirePlayingSound;

        /** 2-6 alphanum chars
         ** said before each character sentence
         ** only when other players in same party / near
         */
        Sound _soundId;
        Sound _soundTalking;
        Sound _soundBreath;
        Sound _soundInitSprint;
        Sound _soundSprint;

        // ---------- clothes size ----------
        // TODO: binary field
        unsigned char sizeShoes;
        unsigned char sizeTorso;
        unsigned char sizeHands;
        unsigned char sizeSoulders;
        unsigned char legLength;
        unsigned char armLength; // we could consider == legLength
};

#endif /* !CHARACTER_HH_ */
